//------------------------------------------------------------------------------
// Copyright (C) 2007-2008 Samuel Lacroix
// This file is part of Visual Local History 2005
// 
// Visual Local History 2005 is free software; you can redistribute it
// and/or modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the License,
// or (at your option) any later version.
// 
// Visual Local History 2005 is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with Visual Local History 2005; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
//------------------------------------------------------------------------------


#pragma once

using namespace System;
using namespace Extensibility;
using namespace EnvDTE;
using namespace EnvDTE80;
using namespace Microsoft::VisualStudio::CommandBars;
using namespace Microsoft::Win32;
using namespace System::Resources;
using namespace System::Reflection;
using namespace System::Globalization;
using namespace System::IO;
using namespace System::Collections;


namespace HistoryAddIn
{
    ref class HistoryWindow;
    ref class FormConfig;
    ref class Config;

	/// <summary>The object for implementing an Add-in.</summary>
	/// <seealso class='IDTExtensibility2' />
	public ref class Connect : public IDTExtensibility2, public IDTCommandTarget
	{
	public:
	//==============================================================================
	// Wizard-generated members
	//==============================================================================
		
		/// <summary>Implements the constructor for the Add-in object. Place your initialization code within this method.</summary>
		Connect()
		{
		    ::CreateMutex(NULL, FALSE, "{ED3D083C-FE2E-4547-B503-6090439B0D4E}"); // this mutex is used during installation and uninstallation to prevent the user from installing/uninstalling VLH2005 while it is running
		    TempFiles = gcnew Generic::List<String^>;
		    BackupTempFiles = gcnew Hashtable;
		    BackupTempFileSources = gcnew Hashtable;
		}

		/// <summary>Implements the OnAddInsUpdate method of the IDTExtensibility2 interface. Receives notification when the collection of Add-ins has changed.</summary>
		/// <param term='custom'>Array of parameters that are host application specific.</param>
		/// <seealso class='IDTExtensibility2' />	
		virtual void OnAddInsUpdate(System::Array ^%custom);

		/// <summary>Implements the OnBeginShutdown method of the IDTExtensibility2 interface. Receives notification that the host application is being unloaded.</summary>
		/// <param term='custom'>Array of parameters that are host application specific.</param>
		/// <seealso class='IDTExtensibility2' />
		virtual void OnBeginShutdown(System::Array ^%custom);

		/// <summary>Implements the OnConnection method of the IDTExtensibility2 interface. Receives notification that the Add-in is being loaded.</summary>
		/// <param term='application'>Root object of the host application.</param>
		/// <param term='connectMode'>Describes how the Add-in is being loaded.</param>
		/// <param term='addInInst'>Object representing this Add-in.</param>
		/// <seealso class='IDTExtensibility2' />
		virtual void OnConnection(System::Object ^Application, ext_ConnectMode ConnectMode, System::Object ^AddInInst, System::Array ^%custom);

		/// <summary>Implements the OnStartupComplete method of the IDTExtensibility2 interface. Receives notification that the host application has completed loading.</summary>
		/// <param term='custom'>Array of parameters that are host application specific.</param>
		/// <seealso class='IDTExtensibility2' />
		virtual void OnStartupComplete(System::Array ^%custom);

		/// <summary>Implements the OnDisconnection method of the IDTExtensibility2 interface. Receives notification that the Add-in is being unloaded.</summary>
		/// <param term='disconnectMode'>Describes how the Add-in is being unloaded.</param>
		/// <param term='custom'>Array of parameters that are host application specific.</param>
		/// <seealso class='IDTExtensibility2' />
		virtual void OnDisconnection(ext_DisconnectMode removeMode, System::Array ^%custom);

		/// <summary>Implements the Exec method of the IDTCommandTarget interface. This is called when the command is invoked.</summary>
		/// <param term='commandName'>The name of the command to execute.</param>
		/// <param term='executeOption'>Describes how the command should be run.</param>
		/// <param term='varIn'>Parameters passed from the caller to the command handler.</param>
		/// <param term='varOut'>Parameters passed from the command handler to the caller.</param>
		/// <param term='handled'>Informs the caller if the command was handled or not.</param>
		/// <seealso class='Exec' />
		virtual void Exec(String ^CmdName, vsCommandExecOption ExecuteOption, Object ^%VariantIn, Object ^%VariantOut, bool %handled);

		/// <summary>Implements the QueryStatus method of the IDTCommandTarget interface. This is called when the command's availability is updated</summary>
		/// <param term='commandName'>The name of the command to determine state for.</param>
		/// <param term='neededText'>Text that is needed for the command.</param>
		/// <param term='status'>The state of the command in the user interface.</param>
		/// <param term='commandText'>Text requested by the neededText parameter.</param>
		/// <seealso class='Exec' />
		virtual void QueryStatus(String ^CmdName, vsCommandStatusTextWanted NeededText, vsCommandStatus %StatusOption, Object ^%CommandText);


	//==============================================================================
	// Personal members
	//==============================================================================

		void UpdateHistoryWindow();
		static String^ DirRelativeDirTo(String^ From, String^ To);
		String^ GetHistoryPath();
 		String^ ReadValueFromLayoutFile(String^ Key);
		void CleanHistoryDirectory();
		bool StringMatchPatterns(String^ Str, array<String^>^ Pattern);
		static String^ RemoveQuotes(String^ Str);
		bool CheckForNewVersion();
		
		// temp files used (to delete them at the end)
        Generic::List<String^>^ TempFiles;
        
        // temp file associated with a backup
        Hashtable^ BackupTempFiles; // key=backup full path, value=temp file full path
        Hashtable^ BackupTempFileSources; // key=temp file full path, value=real path of current revision
        
        // current document (see OnWindowActivated)
        Document^ realCurrentDocument;

        // Configuration
        Config^ config;
        FormConfig^ formConfig;
        
        // Settings
        String^ historyHiddenDirPrefix;
        String^ layoutFileName;
        static wchar_t DiffToolArgsChar = '%';
        ref struct DiffToolArgs
        {
            static String^ CurrentRevision = "current";    
            static String^ SelectedBackup = "old";    
            static String^ CurrentRevisionName = "currentname";    
            static String^ SelectedBackupName = "oldname";    
        };

	private:
		// Misc private methods
		void Init();
		void CreateHistoryWindow();
		void BindEventHandlers();
    	void WriteValueToLayoutFile(String^ Key, String^ Value);
    	void BuildLayout(Hashtable^ layout, ProjectItems^ projectItems); 
    	void RemoveAttributeRecursivelyInDir(FileAttributes Attribute, DirectoryInfo^ di);
		
		// DTE Event Handlers
		void OnDocumentSaved(Document^ document);
		void OnDocumentClosing(Document^ document);
		void OnSolutionOpened();
		void OnSolutionClosed();
		void OnSolutionClosing();
		void BuildProjectItemsList(Generic::List<ProjectItem^>^ projectItemList, ProjectItems^ projectItems);
		void OnSolutionRenamed(String^ oldName);
		void OnWindowActivated(Window^ gotFocus, Window^ lostFocus);
		void OnItemRenamed(ProjectItem^ item, String^ oldName);
		
		// Handles on VS and on self
		DTE2 ^_applicationObject;
		AddIn ^_addInInstance;
		
		// GUI handles
		Window^ toolWindow;
        HistoryWindow^ historyWindow;
        
        // DTE Events
        DocumentEvents^ docEvents;
        SolutionEvents^ solEvents;
        WindowEvents^ winEvents;
        ProjectItemsEvents^ projItemsEvents;
        
        // history of the current solution
        String^ historyPath;
   	};
}
